﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.HeadCounter.Data.Models;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Services.Forums
{
    public class ForumRaiderSummaryPost
    {
        private static readonly IHeadCounterService HeadCounterService = ObjectFactory.GetInstance<IHeadCounterService>();
        private static readonly Options Options = ObjectFactory.GetInstance<IHeadCounterService>().Options;

        private readonly IForumFormatter format;

        private int _commaCount;
        private string _post;

        public ForumRaiderSummaryPost(IForumFormatter format)
        {
            this.format = format;
        }

        public string Generate(Raider raider)
        {
            _commaCount = 0;
            _post = format.Colour(format.Bold(raider.WebSafeName), raider.Class.ClassContrastColourString()) + " : ";

            PostAttendance(raider);
            PostLootMetrics(raider);

            _post += Environment.NewLine;

            return _post;
        }

        private void PostAttendance(Raider raider)
        {
            if (Options.ShowShortPeriodAttendance)
            {
                _post += Separator() + ShortPeriodAttendancePostlet(raider);
            }

            if (Options.ShowLongPeriodAttendance)
            {
                _post += Separator() + LongPeriodAttendancePostlet(raider);
            }

            if (Options.ShowLifetimeAttendance)
            {
                _post += Separator() + LifetimeAttendancePostlet(raider);
            }

            if (Options.ShowShortPeriodAllAttendance)
            {
                _post += Separator() + ShortPeriodAllAttendancePostlet(raider);
            }

            if (Options.ShowLongPeriodAllAttendance)
            {
                _post += Separator() + LongPeriodAllAttendancePostlet(raider);
            }

            if (Options.ShowLifetimeAllAttendance)
            {
                _post += Separator() + LifetimeAllAttendancePostlet(raider);
            }

            _post += Environment.NewLine;
            _commaCount = 0;
        }

        private void PostLootMetrics(Raider raider)
        {
            if (Options.ShowShortPeriodLootCount)
            {
                _post += Separator() + format.Italic(" 6wk Items = " + string.Format("{0}", raider.ShortPeriodLootCount));
            }

            if (Options.ShowShortPeriodLootRate)
            {
                _post += Separator() + format.Italic(" 6wk Rate = " + string.Format("{0:F2}", raider.ShortPeriodLootRate));
            }

            if (Options.ShowShortPeriodWeightedLootRate)
            {
                _post += Separator() + format.Italic(" 6wk Weighted Rate = " + string.Format("{0:F2}", raider.ShortPeriodWeightedLootRate));
            }

            if (Options.ShowLongPeriodLootCount)
            {
                _post += Separator() + format.Italic(" 12wk Items = " + string.Format("{0}", raider.LongPeriodLootCount));
            }

            if (Options.ShowLongPeriodLootRate)
            {
                _post += Separator() + format.Italic(" 12wk Rate = " + string.Format("{0:F2}", raider.LongPeriodLootRate));
            }

            if (Options.ShowLongPeriodWeightedLootRate)
            {
                _post += Separator() + format.Italic(" 12wk Weighted Rate = " + string.Format("{0:F2}", raider.LongPeriodWeightedLootRate));
            }

            if (Options.ShowLifetimeLootCount)
            {
                _post += Separator() + format.Italic(" Items = " + string.Format("{0}", raider.LifetimeLootCount));
            }

            if (Options.ShowLifetimeLootRate)
            {
                _post += Separator() + format.Italic(" Rate = " + string.Format("{0:F2}", raider.LifetimeLootRate));
            }

            if (Options.ShowLifetimeWeightedLootRate)
            {
                _post += Separator() + format.Italic(" Weighted Rate = " + string.Format("{0:F2}", raider.LifetimeWeightedLootRate));
            }

            _post += Environment.NewLine;
            _commaCount = 0;
        }

        private void PostLootPriority(Raider raider)
        {
            if (Options.ShowShortPeriodLootPriority)
            {
                _post += Separator() + format.Bold(" 6wk Priority = " + string.Format("{0}", raider.ShortPeriodLootPriority));
            }

            if (Options.ShowLongPeriodLootPriority)
            {
                _post += Separator() + format.Bold(" 12wk Priority = " + string.Format("{0}", raider.LongPeriodLootPriority));
            }

            if (Options.ShowShortPeriodLootPriority)
            {
                _post += Separator() + format.Bold(" Priority = " + string.Format("{0}", raider.LifetimeLootPriority));
            }

            _post += Environment.NewLine;
            _commaCount = 0;
        }


        private string Separator()
        {
            var separator = "";
            if (_commaCount >= 6)
            {
                _commaCount = 0;
                separator = Environment.NewLine;
            }
            else
            {
                if (_commaCount > 0)
                {
                    separator = ", ";
                }

                _commaCount++;
            }

            return separator;
        }

        private string ShortPeriodAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.ShortPeriodAttendance);
            var percent = string.Format("{0:0%}", raider.ShortPeriodAttendance);

            return format.Italic("6wk% = " + format.Colour(percent, colour));
        }

        private string LongPeriodAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.LongPeriodAttendance);
            var percent = string.Format("{0:0%}", raider.LongPeriodAttendance);

            return format.Italic("12wk% = " + format.Colour(percent, colour));
        }

        private string LifetimeAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.LifetimeAttendance);
            var percent = string.Format("{0:0%}", raider.LifetimeAttendance);

            return format.Italic("Att% = " + format.Colour(percent, colour));
        }

        private string ShortPeriodAllAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.ShortPeriodAllAttendance);
            var percent = string.Format("{0:0%}", raider.ShortPeriodAllAttendance);

            return format.Italic("6wk% (inc. Optional) = " + format.Colour(percent, colour));
        }

        private string LongPeriodAllAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.LongPeriodAllAttendance);
            var percent = string.Format("{0:0%}", raider.LongPeriodAllAttendance);

            return format.Italic("12wk% (inc. Optional) = " + format.Colour(percent, colour));
        }

        private string LifetimeAllAttendancePostlet(Raider raider)
        {
            var colour = GetAttendanceColour(raider.LifetimeAllAttendance);
            var percent = string.Format("{0:0%}", raider.LifetimeAllAttendance);

            return format.Italic("Att% (inc. Optional) = " + format.Colour(percent, colour));
        }

        private string GetAttendanceColour(double attendance)
        {
            if (attendance >= Options.HighAttendancePercentage / 100.0)
            {
                return "Black";
            }

            if (attendance >= Options.GoodAttendancePercentage / 100.0)
            {
                return "#0070dd";
            }

            if (attendance >= Options.FairAttendancePercentage / 100.0)
            {
                return "Green";
            }

            return "Red";
        }
    }
}
